import PySpin
import numpy as np
from PyQt5 import QtCore, QtGui, QtWidgets
import enum

from PyQt5.QtCore import pyqtSlot

system = None
cam_list = None
namesCamsToUse = {0: 'Blackfly BFLY-U3-23S6M'}

class FlirCam(QtCore.QObject, PySpin.ImageEventHandler):
    #注意，自定义信号只能放在初始化的前面
    imageArrived = QtCore.pyqtSignal(np.ndarray, int)

    def __init__(self):
        super().__init__()
        global system, cam_list
        self.system = PySpin.System.GetInstance()
        self.cam_list = self.system.GetCameras()
        num_cam = self.cam_list.GetSize()
        self.camList = []
        self.imageCount = 0

        print(num_cam)
        if num_cam <= 0:
            self.cam_list.Clear()
            self.system.ReleaseInstance()
            print('2')
            raise PySpin.SpinnakerException('Not enough camera')


    def openCommunications(self,camsToUse):
        self.camNames = camsToUse
        camContext = 0
        print('*', self.camNames.values())
        for i,self.cam in enumerate(self.cam_list):
            try:
                self.cam.Init()
                self.cam.RegisterEventHandler(self)

                if PySpin.CStringPtr(self.cam.GetTLDeviceNodeMap().GetNode('DeviceModelName')).GetValue() not in self.camNames.values():
                    self.cam.DeInit()
                else:
                    camContext = self.setCamContextByKey(PySpin.CStringPtr(self.cam.GetTLDeviceNodeMap().GetNode('DeviceModelName')).GetValue())
                    self.camList.append(i)
                    print('打开设备ok')

            except:
                print('无法打开交流失败')

    def setCamContextByKey(self,devicemodelname):
        for key, value in self.camNames.items():
            if value == devicemodelname:
                return key

    # def setCamParameters(self, ex):
    def linshicamBeginAcquisition(self):
        self.cam.AcquisitionMode.SetValue(PySpin.AcquisitionMode_Continuous)
        self.cam.BeginAcquisition()

    def getMinExposure(self):
        return self.cam.ExposureTime.GetMin()

    def getMaxExposure(self):
        return self.cam.ExposureTime.GetMax()

    def getGain(self):
        return self.cam.Gain.GetValue()

    def getMinGain(self):
        return self.cam.Gain.GetMin()

    def getMaxGain(self):
        return self.cam.Gain.GetMax()

    def setExposure(self, exposure_time):
        if self.cam.ExposureAuto.GetAccessMode() != PySpin.RW:
            print('Unable to disable automatic exposure. Aborting...')
            return False

        self.cam.ExposureAuto.SetValue(PySpin.ExposureAuto_Off)
        print('自动曝光关闭...')
        if self.cam.ExposureTime.GetAccessMode() != PySpin.RW:
            print('Unable to set exposure time. Aborting...')
            return False
        exposure_time = min(self.cam.ExposureTime.GetMax(), exposure_time)
        exposure_time = max(self.cam.ExposureTime.GetMin(), exposure_time)
        self.cam.ExposureTime.SetValue(exposure_time)

    def setGain(self, gain):
        if self.cam.GainAuto.GetAccessMode() != PySpin.RW:
            print('Unable to disable automatic exposure. Aborting...')
            return False

        self.cam.GainAuto.SetValue(PySpin.GainAuto_Off)
        print('自动增益关闭...')
        if self.cam.Gain.GetAccessMode() != PySpin.RW:
            print('Unable to set exposure time. Aborting...')
            return False
        self.cam.Gain.SetValue(gain)
        print('硬件层%i' %gain)

    def autoExposure(self, bstate):
        if bstate:
            if self.cam.ExposureAuto.GetAccessMode() != PySpin.RW:
                print('Unable to disable automatic exposure. Aborting...')
                return False
            self.cam.ExposureAuto.SetValue(PySpin.ExposureAuto_Continuous)
        else:
            if self.cam.ExposureAuto.GetAccessMode() != PySpin.RW:
                print('Unable to disable automatic exposure. Aborting...')
                return False
            self.cam.ExposureAuto.SetValue(PySpin.ExposureAuto_Off)

    def autoGain(self, bstate):
        if bstate:
            if self.cam.GainAuto.GetAccessMode() != PySpin.RW:
                print('Unable to disable automatic exposure. Aborting...')
                return False

            self.cam.GainAuto.SetValue(PySpin.GainAuto_Continuous)
        else:
            if self.cam.GainAuto.GetAccessMode() != PySpin.RW:
                print('Unable to disable automatic exposure. Aborting...')
                return False
            self.cam.GainAuto.SetValue(PySpin.GainAuto_Off)


    def returnCamList(self):
        camList = []
        for i,cam in enumerate(self.cam_list):
            try:
                nodetlmap = cam.GetTLDeviceNodeMap()
                nodetl_model_map = PySpin.CStringPtr(nodetlmap.GetNode('DeviceModelName')) #这里是通过tranfer layer进行查询，不需要相机初始化
                print(type(nodetl_model_map.GetValue()))
                camList.append(nodetl_model_map.GetValue())
            except PySpin.SpinnakerException as ex:
                print('Error: %s' % ex)
        return camList

    def close(self):
        for i,self.cam in enumerate(self.cam_list):
            self.cam.EndAcquisition()
            self.cam.AcquisitionMode.SetValue(PySpin.AcquisitionMode_Continuous)
            self.cam.GainAuto.SetValue(PySpin.GainAuto_Continuous)
            self.cam.ExposureAuto.SetValue(PySpin.ExposureAuto_Continuous)
            self.cam.UnregisterEventHandler(self)
            self.cam.DeInit()
        del self.cam
        self.cam_list.Clear()
        self.system.ReleaseInstance()

    def OnImageEvent(self, image):
        print('进入到触发事件')
        if image.IsIncomplete():
            print('图像不完整,图像的状态为%i...' %image.GetImageStatus())
        else:
            image_converted = image.Convert(PySpin.PixelFormat_RGB8,
                                            PySpin.NEAREST_NEIGHBOR)
            image_array = image_converted.GetNDArray()
            self.imageArrived.emit(image_array, self.imageCount)
            self.imageCount += 1





if __name__ == '__main__':
    cam = FlirCam()
    cam.returnCamList()
    cam.openCommunications(namesCamsToUse)
    print(cam.getMinExposure())
    print(cam.getMaxExposure())
    print(cam.getMinGain())
    print(cam.getMaxGain())
    # cam.setGain(2)
    cam.linshicamBeginAcquisition()
    cam.setExposure(50)

    cam.close()




